package com.bdcom.autotest.interaction.socket;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import javax.tools.Tool;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.bdcom.autotest.interaction.socket.bean.BasePkg;
import com.bdcom.autotest.interaction.step.StepThread;
import com.bdcom.autotest.util.CUtil;
import com.bdcom.autotest.util.Prop;

public class DevSocket implements Runnable {
	
	
	private static Logger log = LoggerFactory.getLogger(DevSocket.class);
	
	
	private StepThread flowThread;
	private HBThread hbthread;
	
	public DevSocket( StepThread flowThread ) {
		
		
		
		this.flowThread = flowThread;
		
		initSocket();
	}
	
	public static String devip = Prop.devConfig.getProperty("devIp");
	public static int devport = Integer.valueOf(Prop.devConfig.getProperty("devPort"));

	public static final int STATUS_OK = 1;
	public static final int STATUS_ERROR = 2;
	
	private int status = STATUS_OK;
	private Socket  socket = null;
	
	private void initSocket() {
		
		CUtil.threadsleep(1000);
		try {
			
			socket = new Socket( devip , devport );
			status = STATUS_OK;
			Thread thread = new Thread(this);
			thread.start();
			
			//启动心跳线程
			hbthread = new HBThread(this);
			Thread thread2 = new Thread(hbthread);
			thread2.start();
			
		}   catch ( Exception e) {
			status = STATUS_ERROR;
			log.error( "" ,e );
		}
		
	}
	
	
	private volatile boolean endFlag = false ;
//	private int count = 0;
     public void run() {
    	 
    	 ByteArrayOutputStream baos = new ByteArrayOutputStream();
    	 
         long startTime = System.currentTimeMillis();
         InputStream is =null;
         while ( !endFlag ) {
             try {
                 if (socket == null || socket.isClosed()) { 
                     socket = new Socket( devip , devport );
                 }
                 is = socket.getInputStream();
                 int size = is.available();
                 if (size <= 0) {
                	// 如果超过3600秒没有收到服务器发回来的信息，说明socket连接可能已经被远程服务器关闭
					if ((System.currentTimeMillis() - startTime) > 60 * 60 * 1000) {
						//socket 断开!!!
						socketLostError();
						startTime = System.currentTimeMillis();
					}
					CUtil.threadsleep(  200  );
					continue;
                 } else {
                     startTime = System.currentTimeMillis();
                 }
                 byte[] msgBytes = new byte[size];
                 is.read(msgBytes);
//                 if(count%2 == 0){
//                	 msgBytes = new byte[]{(byte)0x9E,(byte)0x01};
//                 }else{
//                	 msgBytes = new byte[]{(byte)0x00,(byte)0x03,(byte)0xAE,(byte)0xAE,(byte)0x03,(byte)0xAE};
//                 }
//                 msgBytes = new byte[]{(byte)0x9E,(byte)0x01,(byte)0x00,(byte)0x01,(byte)0xAE,(byte)0xAE,
//                		 (byte)0x9E,(byte)0x01,(byte)0x00,(byte)0x01,(byte)0xAE,(byte)0xAE,
//                		 (byte)0x9E,(byte)0x01,(byte)0x00,(byte)0x01,(byte)0xAE,(byte)0xAE};
//                 count++;
                 baos = handlerBytes(msgBytes , baos);
                 
             } catch (Exception e) {
                log.error( "" , e); 
                 try {
                     socket.close();
                 } catch (Exception e1) {
                     e1.printStackTrace();
                 }
             }
         }
     }
	
	
	private void socketLostError() {
		// 中断测试
		//
		
		try {
			socket.close();
		} catch (IOException e) {
			log.error( "" ,e );
		} 
		this.status = STATUS_ERROR;
	}


	private ByteArrayOutputStream handlerBytes(byte[] msgBytes, ByteArrayOutputStream baos) {
		int starti = -2;
		int endi = -2;
		int pkgLen = -2;//报文长度中的len
		int length = msgBytes.length;
		for(   int i=0; i<length   ;i++  ) {
			byte tmp = msgBytes[i];
			if(  tmp==BasePkg.START_FlAG  ) {
				starti = i;
				if(i+3<length){
					pkgLen = DataUtil.bytes2Int(new byte[]{msgBytes[i+2],msgBytes[i+3]});
				}
			}else if( pkgLen!=-2&& tmp==BasePkg.STOP_FLAG ) {
				endi = i;
				if(starti+pkgLen+4 == i){//有len,找到结束位
					if(  starti != -1 && starti != -2 ) {
						int len = endi - starti + 1 ;
						byte[] amsg = new byte[len];
						System.arraycopy(msgBytes, starti, amsg, 0, len);
						postAMsg( amsg  );
					}
					else {
						byte[] msg1 = baos.toByteArray();
						int len = endi + 1 ;
						byte[] msg2 = new byte[len];
						System.arraycopy(msgBytes, 0, msg2, 0, len);
						byte[] amsg = DataUtil.arrayJoin(msg1  , msg2);
						postAMsg( amsg  );
						try {
							baos.close();
						} catch (IOException e) {
							log.error( "" ,e );
						}
						baos = new ByteArrayOutputStream();
					}
					starti = -1;
					endi = -1;
				}
			}else if(pkgLen==-2&& tmp==BasePkg.STOP_FLAG){
				endi = i;
				byte[] msg1 = baos.toByteArray();
				int len = endi + 1 ;
				byte[] msg2 = new byte[len];
				System.arraycopy(msgBytes, 0, msg2, 0, len);
				byte[] amsg = DataUtil.arrayJoin(msg1  , msg2);
				if(amsg.length>3){
					int tmpLen = DataUtil.bytes2Int(new byte[]{amsg[2],amsg[3]});//获得len
					if(tmpLen+4-msg1.length == endi){
						postAMsg( amsg  );
						try {
							baos.close();
						} catch (IOException e) {
							log.error( "" ,e );
						}
						baos = new ByteArrayOutputStream();
					}
				}
				starti = -1;
				endi = -1;
			}
		}
		if(  starti>=0 && (  endi==-1 || endi==-2 ) ) {
			int len = length  -  starti ;
			byte[] msg = new byte[len];
			System.arraycopy(msgBytes, starti , msg, 0, len );
			try {
				baos.write(msg);
			} catch (IOException e) {
				log.error( "" ,e );
			}
		}
		
		if(  starti==-2 && endi==-2  ) {
			try {
				baos.write(msgBytes);
			} catch (IOException e) {
				log.error( "" ,e );
			}
		}
		return baos;
	}
	
	private Map<String, List<BasePkg> > cmdToPkg = new LinkedHashMap<>();
	private ReentrantLock lock = new ReentrantLock();

	private void postAMsg(byte[] amsg) {
		BasePkg fromBytes = BasePkg.fromBytes(amsg);
		byte cmd = fromBytes.getCmd();
		
		String key = "" + cmd;
		try {
			lock.lock();
			List<BasePkg> list = cmdToPkg.get(key);
			if(  list == null ) {
				list = new ArrayList<BasePkg>();
				cmdToPkg.put(key, list);
			}
			list.add(fromBytes);
		}finally {
			lock.unlock();
		}
	}
	
	public BasePkg pollAMsg( byte cmd ) {
		if( flowThread.isEndFlag() ){
			return new BasePkg();
		}
		String key = "" + cmd;
		try {
			lock.lock();
			List<BasePkg> list = cmdToPkg.get(key);
			if( CollectionUtils.isEmpty( list  )   ) {
				return null;
			}
			return list.remove(0);
		}finally {
			lock.unlock();
		}
	}
	
	public List<BasePkg> pollMsgs( byte cmd ) {
		String key = "" + cmd;
		try {
			lock.lock();
			List<BasePkg> list = cmdToPkg.get(key);
			if( CollectionUtils.isEmpty( list  )   ) {
				return null;
			}
			return list;
		}finally {
			lock.unlock();
		}
	}
	


	public void writeMsg(byte[] bytes) {
		// 要发送给服务器的信息
		OutputStream os = null;
		try {
			os = socket.getOutputStream();
			os.write(bytes);
			os.flush();
		} catch (Exception e) {
			log.error("", e);
		} finally {

		}
	}
	
	
	public void shutdown() {
		hbthread.shutdown();
		this.endFlag = true;
		try {
			Thread.sleep(2000);
			socket.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	

	public boolean isOk() {
		return status == STATUS_OK;
	}

	public void heartbeat() {
		
	}





}
